package edu.pku.sei.transformation.tgg.adapter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import edu.pku.sei.transformation.editor.model.Expression;
import edu.pku.sei.transformation.editor.model.GraphicalDomain;
import edu.pku.sei.transformation.editor.model.Rule;
import edu.pku.sei.transformation.editor.model.variable.ConnectionVariable;
import edu.pku.sei.transformation.editor.model.variable.ObjectVariable;
import edu.pku.sei.transformation.tgg.rule.IConstraint;
import edu.pku.sei.transformation.tgg.rule.IDomain;
import edu.pku.sei.transformation.tgg.rule.IEdge;
import edu.pku.sei.transformation.tgg.rule.IModelParameter;
import edu.pku.sei.transformation.tgg.rule.INode;
import edu.pku.sei.transformation.tgg.rule.IPattern;
import edu.pku.sei.transformation.tgg.rule.IRule;
import edu.pku.sei.transformation.tgg.rule.ITGGTransformation;

public class RuleAdapter implements IRule {
	Rule element;
	ITGGTransformation owner;
	IPattern leftPattern = new PatternAdapter();
	IPattern rightPattern = new PatternAdapter();
	List<IDomain> domains = new ArrayList<IDomain>();
	HashMap<String, INode> nodeList = new HashMap<String, INode>();
	List<IConstraint> constraints = new ArrayList<IConstraint>();
	
	
	public RuleAdapter(Rule r, ITGGTransformation owner) {
		this.element = r;
		this.owner = owner;
		
		for(Object obj : r.getDomains()) {
			if (obj instanceof GraphicalDomain) {
				GraphicalDomain d = (GraphicalDomain) obj;
				String typedModelName = d.getTypedModel().getName();
				IDomain domain = null;
				for(IModelParameter p : owner.getModelParameters()) {
					if (p.getName().equals(typedModelName)) {
						domain = new DomainAdapter(d, p);
						domains.add(domain);
						p.addDomain(domain);
					}
				}
				
				for (Object temp : d.getPattern().getNodes()) {
					if (temp instanceof ObjectVariable) {
						ObjectVariable ov = (ObjectVariable) temp;
						INode node = null;
						if (ov.isFixed()) {
							node = new NodeAdapter(ov, leftPattern, domain);
							leftPattern.getNodes().add(node);
							domain.getNodes().add(node);
						} else {
							node = new NodeAdapter(ov, rightPattern, domain);
							rightPattern.getNodes().add(node);
							domain.getNodes().add(node);
						}
						nodeList.put(node.getID(), node);
						
						for(Object e : ov.getExpressions()) {
							Expression exp = (Expression) e; 
							constraints.add(new ConstraintAdapter(exp, node));
						}
					}
				}
				
				for (Object temp : d.getPattern().getLinks()) {
					if (temp instanceof ConnectionVariable) {
						ConnectionVariable cv = (ConnectionVariable) temp;
						String sourceID = String.valueOf(cv.getSource().getElementID());
						String targetID = String.valueOf(cv.getTarget().getElementID());
						IEdge edge = null;
						if (cv.isFixed()) {
							edge = new EdgeAdapter(cv, leftPattern, nodeList.get(sourceID), nodeList.get(targetID));
							nodeList.get(sourceID).getOutGoingEdges().add(edge);
							leftPattern.getEdges().add(edge);
						} else {
							edge = new EdgeAdapter(cv, rightPattern, nodeList.get(sourceID), nodeList.get(targetID));
							nodeList.get(sourceID).getOutGoingEdges().add(edge);
							rightPattern.getEdges().add(edge);
						}
					}
				}
			}
		}
	}
	@Override
	public List<IConstraint> getConstraints() {
		return constraints;
	}

	@Override
	public List<IDomain> getDomains() {
		return domains;
	}

	@Override
	public IPattern getLeftPattern() {
		return leftPattern;
	}

	@Override
	public List<INode> getNodes() {
		ArrayList<INode> list = new ArrayList<INode>();
		list.addAll(nodeList.values());
		return list;
	}

	@Override
	public IPattern getRightPattern() {
		return rightPattern;
	}

	@Override
	public String getID() {
		return String.valueOf(element.getElementID());
	}
	@Override
	public String getName() {
		return element.getName();
	}

}
